/* File:        	Query.java
* Package:			org.esi.authz.pdp.core
* Created:      	29-abr-2011
* Last Changed: 	0:08:10
* Author:       	Borja Urkizu borja.urquizu@tecnalia.com
*
*   
* History:
*  Revision 1.0.0.0  
* 
* Tecnalia Research and Innovation
*/
package com.tecnalia.authz.pdp.core.xacml;

import java.io.InputStream;

import org.jboss.security.xacml.core.JBossPDP;
import org.jboss.security.xacml.interfaces.PolicyDecisionPoint;
import org.jboss.security.xacml.interfaces.RequestContext;
import org.jboss.security.xacml.interfaces.ResponseContext;

import com.tecnalia.authz.common.Resource;
import com.tecnalia.authz.common.XACMLConstants;
import com.tecnalia.authz.common.request.Request;
import com.tecnalia.authz.common.response.Response;
import com.tecnalia.authz.pdp.config.PDPConfig;
import com.tecnalia.authz.pdp.core.PDPEngine;

// TODO: Auto-generated Javadoc
/**
 * The Class Query.
 */
public class XACMLQueryImpl implements IXACMLQuery {

    /** The pdp. */
    private static PolicyDecisionPoint pdp = null;

    /**
     * Instantiates a new xACML query impl.
     */
    public XACMLQueryImpl(){
        pdp = this.getPDP(PDPEngine.getPDPcfg().getPdpConfig());

    }
    
    
    /**
     * Instantiates a new xACML query impl.
     *
     * @param pdpconfig the pdpconfig
     */
    public XACMLQueryImpl(PDPConfig pdpconfig){
        pdp = this.getPDP(pdpconfig);

    }
    
	/**
	 * Gets the pDP.
	 *
	 * @param PDPcfg the pD pcfg
	 * @return the pDP
	 */
	private PolicyDecisionPoint getPDP(PDPConfig PDPcfg)
	{
		
		Resource res = new Resource(); 
		InputStream is = res.getResourceAsStream(PDPcfg.getPrimaryPolicyConfiguration());

		return new JBossPDP(is);
		
	}

    
	/* (non-Javadoc)
	 * @see org.esi.authz.pdp.core.IXACMLQuery#evaluate(org.jboss.security.xacml.interfaces.RequestContext[], int)
	 */
	/* (non-Javadoc)
	 * @see com.tecnalia.authz.pdp.core.xacml.IXACMLQuery#evaluate(org.jboss.security.xacml.interfaces.RequestContext[], int)
	 */
	@Override
	public ResponseContext[] evaluate(RequestContext[] requestContext, int queryMode){
		
		ResponseContext[] responseListAuthz = new ResponseContext[requestContext.length];
		
		for (int i = 0; i < requestContext.length; i++) {
			ResponseContext responseAuthz = this.evaluate(requestContext[i],queryMode);			
			responseListAuthz[i] = responseAuthz;

		}

		return responseListAuthz;

	}

	/* (non-Javadoc)
	 * @see org.esi.authz.pdp.core.IXACMLQuery#evaluate(org.jboss.security.xacml.interfaces.RequestContext, int)
	 */
	/* (non-Javadoc)
	 * @see com.tecnalia.authz.pdp.core.xacml.IXACMLQuery#evaluate(org.jboss.security.xacml.interfaces.RequestContext, int)
	 */
	@Override
	public ResponseContext evaluate(RequestContext requestContext, int queryMode) {        
		
		ResponseContext responseAuthz = null;
		try {
			//Evaluate the request in Simply Mode
			if(queryMode == XACMLConstants.XACML_QUERY_Simple){
					responseAuthz = this.evaluateRequest(requestContext);
			}
			
			//Evaluate the request in Flexible Mode
			if(queryMode == XACMLConstants.XACML_QUERY_Flexible){
				responseAuthz = this.evaluateFlexibleRequest(requestContext);
			}
			
			//Evaluate the request in Flexible Mode
			if(queryMode == XACMLConstants.XACML_QUERY_Strict){
				responseAuthz = this.evaluateStrictRequest(requestContext);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return  responseAuthz;
	
		
	}
    
	
	/**
	 * Evaluate request.
	 *
	 * @param request the request
	 * @return the response context
	 * @throws Exception the exception
	 */
	private ResponseContext evaluateRequest(RequestContext request) throws Exception {        
    	
		if( pdp == null ){
			PDPEngine.logger.info("PDP engine has not been initialized!!!");
		}
		
    	//logger.logBinaryRequest(request);
    	
    	ResponseContext actualResponse = pdp.evaluate(request);
    	
    	//logger.logBinaryResponse(actualResponse);
        
    	return actualResponse;        
    }

	/**
	 * Evaluate request.
	 *
	 * @param request the request
	 * @return the response context[]
	 * @throws Exception the exception
	 */
	private ResponseContext[] evaluateRequest(RequestContext[] request) throws Exception {
    	    	
    	ResponseContext[] resList = new ResponseContext[request.length]; 	
    	
    	
    	for (int i = 0; i < request.length; i++) {
    		resList[i] = (this.evaluateRequest(request[i]));
			
		}    	
    	
    	return resList;
    }

	/**
	 * Evaluate flexible request.
	 *
	 * @param req the req
	 * @return the response context
	 * @throws Exception the exception
	 */
	private ResponseContext evaluateFlexibleRequest(RequestContext req) throws Exception {
    	
		PDPEngine.logger.debug("CONTUR REQUEST");
		PDPEngine.logger.logBinaryRequest(req);
	    	
    	Request requestContur = new Request(); 
    	requestContur.setRequestContext(req);
		RequestContext[] request = requestContur.flexibleRequestContext();

		PDPEngine.logger.debug("FLEXIBLE REQUEST");
    	
		for (int i = 0; i < request.length; i++) {
			PDPEngine.logger.logBinaryRequest(request[i]);

		}
		
    	ResponseContext[] respList = new ResponseContext[request.length];  	
    	
    	for (int i = 0; i < request.length; i++) {
    		respList[i] = (this.evaluateRequest(request[i]));
			
		}    	
    	
    	PDPEngine.logger.debug("FLEXIBLE RESPONSE");
    	for (int i = 0; i < respList.length; i++) {
    		PDPEngine.logger.debug("INDIVIDUAL RESPONSE");
    		PDPEngine.logger.logBinaryResponse(respList[i]);
		}

    	Response respAuthz = new Response();
    	respAuthz.setListResponse(respList);
    	ResponseContext parseRes = respAuthz.flexibleResponseContext(request);
    	PDPEngine.logger.debug("CONTUR RESPONSE");
    	PDPEngine.logger.logBinaryResponse(parseRes);

    	return parseRes;
    }


    /**
     * Evaluate strict request.
     *
     * @param req the req
     * @return the response context
     * @throws Exception the exception
     */
    private ResponseContext evaluateStrictRequest(RequestContext req) throws Exception {
    	PDPEngine.logger.debug("CONTUR REQUEST");
    	PDPEngine.logger.logBinaryRequest(req);
	    	
    	Request requestContur = new Request(); 
    	requestContur.setRequestContext(req);
		RequestContext request = requestContur.strictRequestContext(); 

		PDPEngine.logger.debug("STRICT REQUEST");    	
		PDPEngine.logger.logBinaryRequest(request);
    	
		ResponseContext res= (this.evaluateRequest(request));
			
    	
		PDPEngine.logger.debug("STRICT RESPONSE");
		PDPEngine.logger.logBinaryResponse(res);


    	return res;
    }
	
}
